<script>
import WindowOverlay from '@/components/WindowOverlay.vue'
import { useFloatWindow } from '@/store/float-window'

export default defineComponent({
  props: {
    win: {
      type: Object,
      default: () => ({}),
    },
    title: {
      type: String,
      default: '',
    },
  },
  emits: ['close'],
  setup(props, { emit, slots }) {
    const floatWindowStore = useFloatWindow()
    const title = slots.title || (() => h('div', { class: 'float-window-title' }, props.title))
    const headerRef = ref(null)
    const transition = ref(null)
    const header =
      slots.header ||
      (() =>
        h(
          'div',
          {
            class: 'float-window-header',
            ref: headerRef,
          },
          [
            title(),
            h(WindowOverlay, {
              onWindowMini: () => {
                floatWindowStore.miniWindow(props.win)
              },
              onWindowFull: () => {
                transition.value = 'top 0.3s, left 0.3s, width 0.3s, height 0.3s'
                setTimeout(() => {
                  transition.value = null
                }, 300)
                floatWindowStore.fullWindow(props.win)
              },
              onWindowClose: () => {
                emit('close')
                floatWindowStore.removeWindow(props.win)
              },
            }),
          ]
        ))
    const body = slots.body || (() => h('div', { class: 'float-window-body' }, slots.default && slots.default()))
    const floatWindowRef = ref(null)
    const MINI_WIDTH = 1240
    const MINI_HEIGHT = 768
    const width = ref(MINI_WIDTH)
    const height = ref(MINI_HEIGHT)
    useResizeObserver(
      floatWindowRef,
      useDebounceFn((entries) => {
        const borderBoxSize = entries[0].borderBoxSize[0]
        width.value = borderBoxSize.inlineSize
        height.value = borderBoxSize.blockSize
      }, 300)
    )
    let oldWidth = 0
    let oldHeight = 0
    watch(
      () => props.win.full,
      (v) => {
        if (v) {
          oldWidth = width.value
          oldHeight = height.value
        } else {
          width.value = oldWidth
          height.value = oldHeight
        }
      }
    )
    const { x, y } = useDraggable(floatWindowRef, {
      initialValue: {
        x: window.innerWidth / 2 - MINI_WIDTH / 2,
        y: window.innerHeight / 2 - MINI_HEIGHT / 2,
      },
      containerElement: document.body,
      stopPropagation: true,
      preventDefault: true,
      handle: headerRef,
      disabled: computed(() => props.win.full),
    })
    return () => {
      return h(
        'div',
        {
          class: 'float-window',
          ref: floatWindowRef,
          style: {
            display: props.win.mini ? 'none' : null,
            left: props.win.full ? 0 : `${x.value}px`,
            top: props.win.full ? 0 : `${y.value}px`,
            zIndex: props.win.zIndex,
            height: props.win.full ? '100%' : `${height.value}px`,
            width: props.win.full ? '100%' : `${width.value}px`,
            minHeight: `${MINI_HEIGHT}px`,
            minWidth: `${MINI_WIDTH}px`,
            transition: transition.value,
          },
        },
        [header(), body()]
      )
    }
  },
})
</script>

<style scoped lang="scss">
.float-window {
  $header-height: 40px;
  position: absolute;
  resize: both;
  overflow: hidden;
  border: var(--elp-border);
  box-shadow: var(--elp-box-shadow);
  .float-window-header {
    @include use-flex(center);
    height: $header-height;
    background-color: var(--elp-color-info-light-9);
    padding: 0 var(--elp-border-radius-16);
    .window-overlay {
      position: unset;
      flex: 1;
      width: auto;
      padding-right: unset;
    }
    .float-window-title {
      user-select: none;
    }
    .float-window-operation {
      @include use-flex(center);
    }
  }
  .float-window-body {
    height: calc(100% - $header-height);
    background-color: var(--elp-bg-color);
    & > * {
      border-radius: unset;
    }
  }
}
</style>
